<template>
  <div class="permission-container">
    <el-form :model="permissionForm" :rules="permissionRules" ref="permissionForm" label-width="200px"
      class="demo-ruleForm">
      <el-form-item label="角色名称" prop="role_name">
        <el-input v-model="permissionForm.role_name"></el-input>
      </el-form-item>
      <el-form-item label="数据范围" prop="dept_ids">
        <el-cascader
          @visible-change="visibleChange"
          ref="cascader"
          :clearable="false"
          v-model="permissionForm.dept_ids"
          :options="deptList"
          @change="selectHandle"
          :props="props"></el-cascader>
      </el-form-item>
      <el-form-item label="角色描述" prop="role_describe">
        <el-input v-model="permissionForm.role_describe"></el-input>
      </el-form-item>
      <el-form-item label="角色权限" prop="permission">
        <el-checkbox :indeterminate="allIndeterminate" v-model="allCheck" @change="handleCheckAll">全部选择</el-checkbox>
        <div v-for="(item, index) in permissions" :key="item.identifier" class="level_1">
          <el-row :gutter="20">
            <el-col :span="4">
              <el-checkbox v-model="item.checked" :label="item.title" :indeterminate="checkIndeterminate(item.children)"
                @change="handleCheckboxChanged(item)"></el-checkbox>
            </el-col>
            <el-col :span="20">
              <div v-for="(_item, _index) in item.children" :key="_item.identifier" class="checkbox-dropdown">
                <el-popover placement="bottom" trigger="hover" :open-delay="300" :disabled="!hasChildren(_item)"
                  :append-to-body="false">
                  <div slot="reference">
                    <el-checkbox v-model="_item.checked" :indeterminate="checkIndeterminate(_item.children)"
                      @click.native.stop @change="handleCheckboxChanged(_item, item)">
                      {{ _item.title }}
                      <template v-if="hasChildren(_item)">
                        <i class="el-icon-arrow-down"></i>
                      </template>
                    </el-checkbox>
                  </div>
                  <div class="role-dropdown__list" v-if="hasChildren(_item)">
                    <div class="role-dropdown" v-for="(__item, __index) in _item.children" :key="__item.identifier">
                      <el-popover placement="right" trigger="hover" :open-delay="200" :disabled="!hasChildren(__item)"
                        :append-to-body="false">
                        <div slot="reference" class="role-dropdown__label">
                          <el-checkbox v-model="__item.checked" :indeterminate="checkIndeterminate(__item.children)"
                            @click.native.stop @change="handleCheckboxChanged(__item, _item)">
                            {{ __item.title }}
                            <template v-if="hasChildren(__item)">
                              <i class="el-icon-arrow-right"></i>
                            </template>
                          </el-checkbox>
                        </div>
                        <div class="role-dropdown__list" v-if="hasChildren(__item)">
                          <div class="role-dropdown" v-for="(___item, __index) in __item.children"
                            :key="___item.identifier">
                            <el-popover placement="right" trigger="hover" :open-delay="200"
                              :disabled="!hasChildren(___item)" :append-to-body="false">
                              <div slot="reference" class="role-dropdown__label">
                                <el-checkbox v-model="___item.checked"
                                  :indeterminate="checkIndeterminate(___item.children)" @click.native.stop
                                  @change="handleCheckboxChanged(___item, __item)">{{ ___item.title }}</el-checkbox>
                              </div>
                            </el-popover>
                          </div>
                        </div>
                      </el-popover>
                    </div>
                  </div>
                </el-popover>
              </div>
            </el-col>
          </el-row>
        </div>
      </el-form-item>
      <el-form-item label="">
        <el-button type="primary" size="small" style="margin-top: 15px" @click="saveRolePermission">保存设置</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
import * as API_Auth from '@/api/auth'
import * as API_Menus from '@/api/menus'
import * as API_Setting from '@/api/setting'
import { Foundation } from '~/ui-utils'
export default {
  name: 'rolePermission',
  data() {
    return {
      props: {
        label: 'name',
        value: 'id',
        emitPath: false,
        multiple: true,
        checkStrictly: true
      },
      checked: true,
      deptList: [],
      oneDimensionalList: [], //  源数据平铺成一级节点
      /** 权限 表单 */
      permissionForm: {
        data_scope: 'ALL',
        role_name: '',
        role_describe: ''
      },
      /** 权限 表单规则 */
      permissionRules: {
        role_name: [
          this.MixinRequired('请输入角色名称！'),
          { min: 1, max: 10, message: '长度在 1 到 10 个字符', trigger: 'blur' }
        ]
      },
      permissions: [],
      // 全选状态
      allCheck: false,
      // 全选不确定状态
      allIndeterminate: false,
      isAllSelected: false
    }
  },
  mounted() {
    this.role_id = this.$route.params.id
    this.GET_RolePermission()
  },
  beforeRouteUpdate(to, from, next) {
    this.role_id = to.params.id
    next()
  },
  activated() {
    this.role_id = this.$router.params.id
  },
  watch: {
    role_id: 'GET_RolePermission'
  },
  methods: {
    // 查找全部节点所在的索引
    searchSelectAllNodeIndex() {
      let selectAllOptionIndex = -1
      this.permissionForm.dept_ids.forEach((res, index) => {
        if (res.length === 1) {
          selectAllOptionIndex = index
        }
      })
      return selectAllOptionIndex
    },
    visibleChange(visible) {
      console.log(visible)
      if (visible) {
        this.deptList.unshift({
          id: '全选',
          name: '全选',
          value: '全选'
        })
      } else {
        this.deptList.shift()
      }
    },

    // 选择级联选择器
    async selectHandle(e = []) {
      // 当前选中数量
      const selectLength = e.filter(v => v !== '全选').length
      const has_all_option = e.some(v => { return v === '全选' })
      let dept_ids = this.MixinClone(this.permissionForm.dept_ids)

      if (has_all_option && this.isAllSelected) {
        // 移除了选项中除全部外的某个节点
        this.$refs.cascader.$refs.panel.clearCheckedNodes()
        dept_ids = dept_ids.filter(v => v !== '全选')
        dept_ids.splice(this.searchSelectAllNodeIndex(), 1)
        this.$set(this.permissionForm, 'dept_ids', dept_ids)
        this.isAllSelected = false
      } else if (has_all_option && !this.isAllSelected) {
        // 选中全部节点
        this.isAllSelected = true
        const deptList = this.deptList
        const dept_ids = []
        const loopSelectData = (list) => {
          list.forEach(e => {
            dept_ids.push(e.id)
            if (e.children && e.children.length > 0) {
              loopSelectData(e.children)
            }
          })
        }
        loopSelectData(deptList)
        this.permissionForm.dept_ids = dept_ids
      } else if (!has_all_option && this.isAllSelected) {
        // 取消选中全部节点
        this.isAllSelected = false
        this.$refs.cascader.$refs.panel.clearCheckedNodes()
        this.permissionForm.dept_ids = []
      } else if (selectLength === this.oneDimensionalList.length) {
        this.isAllSelected = true
        dept_ids.unshift('全选')
        this.permissionForm.dept_ids = dept_ids
      }
      this.$nextTick(() => {
        this.$forceUpdate()
      })
    },
    /** 获取部门 */
    GET_DeptList() {
      API_Setting.getDeptList().then(response => {
        this.deptList = Foundation.buildTree(response, '0')
        const oneDimensionalList = []
        const loopData = (list) => {
          list.forEach(e => {
            oneDimensionalList.push(e)
            if (e.children && e.children.length > 0) {
              loopData(e.children)
            }
          })
        }
        loopData(response)
        this.oneDimensionalList = oneDimensionalList
        if (this.permissionForm.dept_ids.length === oneDimensionalList.length) {
          // 设置数据范围全选
          this.permissionForm.dept_ids.push('全选')
          this.isAllSelected = true
        }
      })
    },
    /** 判断是否还有子集 */
    hasChildren(item) {
      return Array.isArray(item.children) && item.children.length !== 0
    },
    /** 全选 */
    handleCheckAll(checked) {
      this.allIndeterminate = false
      this.$set(this, 'permissions', this.setPermissionsCheck(this.permissions, checked))
    },
    /** 选择 */
    handleCheckboxChanged(item, parent) {
      if (item.children && item.children.length) {
        this.$set(item, 'children', this.setPermissionsCheck(item.children, item.checked))
      }
      this.countAllPermissions()
      this.countParentChecked()
    },
    /** 设置权限状态 */
    setPermissionsCheck(permissions, checked) {
      const perm = this.MixinClone(permissions)
      perm.map(item => {
        item.checked = checked
        this.$set(item, 'checked', checked)
        if (item.children && item.children.length) {
          this.$set(item, 'children', this.setPermissionsCheck(item.children, checked))
        }
      })
      return perm
    },
    /** 检测是否有不确定性 */
    checkIndeterminate(permissions) {
      if (!Array.isArray(permissions)) return false
      const _len = permissions.length
      const __len = permissions.filter(item => item.checked).length
      return (__len !== 0) && (_len !== __len)
    },
    /** 获取所有权限展开后的长度、被选中的长度 */
    countAllPermissions(permissions) {
      permissions = permissions || this.permissions
      const _list = []
      permissions.forEach(item => {
        _list.push(item)
        if (item.children) _list.push(...this.countAllPermissions(item.children))
      })
      const length = _list.length
      const length_checked = _list.filter(_item => _item.checked).length
      this.allCheck = length === _list.filter(_item => _item.checked).length
      this.allIndeterminate = (length_checked !== 0) && (length !== length_checked)
      return _list
    },
    /** 计算所有父辈的选中状态 */
    countParentChecked(permissions) {
      permissions = permissions || this.permissions
      permissions.forEach(item => {
        if (item.children && item.children.length) {
          this.countParentChecked(item.children)
          const lenght = item.children.length
          const checked_length = item.children.filter(_item => _item.checked).length
          item.checked = !!checked_length
        }
      })
    },
    /** 保存角色权限 */
    saveRolePermission() {
      this.$refs['permissionForm'].validate(valid => {
        if (valid) {
          let params = {
            ...this.permissionForm,
            menus: this.permissions
          }
          if (!params.dept_ids) {
            this.$message.error('请选择数据范围！')
            return
          }
          params.dept_ids = params.dept_ids.filter(v => v !== '全选')
          if (params.dept_ids) {
            if (this.isAllSelected) {
              params.data_scope = 'ALL'
              params.dept_ids = params.dept_ids.join(',')
            } else {
              params.data_scope = 'DEPT_CUSTOM'
              params.dept_ids = params.dept_ids.join(',')
            }
          }
          this.role_id === 0
            ? API_Auth.addRole(params).then(() => saveSuccess())
            : API_Auth.editRole(this.role_id, params).then(() => saveSuccess())
          const saveSuccess = () => {
            this.$message.success('保存成功！')
            this.$route.params.callback()
            this.$store.dispatch('delCurrentViews', {
              view: this.$route,
              $router: this.$router
            })
          }
        } else {
          this.$message.error('表单填写有误，请检查！')
          return false
        }
      })
    },
    /** 获取权限菜单树 */
    GET_RolePermission() {
      API_Menus.getMenusChildren().then(res => {
        // 如果this.role_id 不为0，说明是编辑。
        if (this.role_id !== 0) {
          API_Auth.getRolePermission(this.role_id).then(response => {
            this.role_id = response.role_id
            this.permissionForm.data_scope = response.data_scope
            this.permissionForm.role_name = response.role_name
            this.permissionForm.role_describe = response.role_describe
            this.permissionForm.dept_ids = response.dept_ids.split(',')
            const checkedIds = this.expandRouters(response.menus)
            this.$set(this, 'permissions', this.filterRoleRouter(res, checkedIds))
            this.countAllPermissions()
            this.GET_DeptList()
          })
        } else {
          this.$set(this, 'permissions', res)
          this.countAllPermissions()
          this.GET_DeptList()
        }
      })
    },
    /** 展开路由的identifier */
    expandRouters(menus) {
      const routers = []
      menus.forEach(item => {
        item.checked && routers.push(item.identifier)
        if (item.children && item.children.length) {
          routers.push(...this.expandRouters(item.children))
        }
      })
      return routers
    },
    /** 递归筛选被选中的路由 */
    filterRoleRouter(routers, ids) {
      const _routers = []
      routers.forEach(item => {
        if (ids.includes(item.identifier) || item.hidden) {
          item.checked = true
        } else {
          item.checked = false
        }
        if (item.children) {
          this.$set(item, 'children', this.filterRoleRouter(item.children, ids))
        }
        _routers.push(item)
      })
      return _routers
    }
  }
}
</script>

<style type="text/scss" lang="scss" scoped>
.permission-container {
  padding: 10px;
  background-color: #fff;
  padding-bottom: 150px;
}

.level_1 {
  padding: 15px 0;
  border-bottom: 1px dashed #e7e7e7;

  &:last-child {
    border-bottom: none
  }
}

/deep/ {
  .el-form-item__label {
    padding-top: 15px;
  }

  .el-form-item__content {
    border-left: 1px solid #e7e7e7;
    padding-left: 20px;
    padding-top: 15px;

    .el-form-item__error {
      padding-left: 20px;
    }
  }

  .el-form-item:last-child {
    .el-form-item__content {
      padding-top: 0;
    }
  }

  .el-form-item:not(:first-child) {
    border-top: 1px solid #e7e7e7;
    position: relative;

    &::after {
      content: ' ';
      width: 1px;
      height: 22px;
      background-color: #e7e7e7;
      position: absolute;
      top: -22px;
      left: 200px;
    }
  }

  .el-button-group {
    display: inline-block;

    .el-button {
      display: inline-block;
      padding: 0;
      border: none;

      &:focus,
      &:hover {
        color: #606266;
        border-color: #fff;
        background-color: #fff;
      }
    }
  }
}

.checkbox-dropdown {
  display: inline-block;
  min-width: 130px;
  cursor: pointer;

  .checked {
    color: #409EFF
  }
}


.role-dropdown {
  display: flex;
  align-items: center;
  width: 25%;
  height: 30px;
  margin-bottom: 10px;

  &:last-child {
    margin-bottom: 0;
  }

  &__label {
    display: flex;
    align-items: center;
    width: 100%;

    /deep/ .el-checkbox__label {
      color: inherit;
    }
  }

  &__list {
    max-height: 320px;
    overflow-y: auto;
  }
}
</style>
